﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;

namespace server
{
    public class UserData
    {
        //XML Style
        //<User>
        //    <UserId></UserId>
        //    <UserName></UserName>
        //    <UserPwd></UserPwd>
        //    <UserInfo>
        //        <QQ></QQ>
        //        <MSN></MSN>
        //        <Email></Email>
        //        <Phone></Phone>
        //    </UserInfo>
        //    <AssignJob>
        //        <ProjId></ProjId>
        //        <Job></Job>
        //    </AssignJob>
        //    *<AssignJob>*
        //</User>
        //*<User>*
        //<Project>
        //    <ProjId></ProjId>
        //    <ProjName></ProjName>
        //</Project>
        //*<Project>*

        static private string UserDataFileName = global::server.Properties.Resources.UserDataFileName;

        /// <summary>
        /// User Information
        /// </summary>
        public class UserInfo
        {
            private string qq;
            private string msn;
            private string email;
            private string phone;
            public string QQ
            {
                get { return qq; }
                set { qq = value; }
            }
            public string MSN
            {
                get { return msn; }
                set { msn = value; }
            }
            public string Email
            {
                get { return email; }
                set { email = value; }
            }
            public string Phone
            {
                get { return phone; }
                set { phone = value; }
            }
        }

        /// <summary>
        /// User and Projects assigned
        /// </summary>
        public class UserAssignProj
        {
            private int projId;
            private string job;
            public int ProjId
            {
                get { return projId; }
                set { projId = value; }
            }
            public string Job
            {
                get { return job; }
                set { job = value; }
            }
        }

        /// <summary>
        /// User Basic
        /// </summary>
        public class User
        {
            private int userId;
            private string userName;
            private string userPwd;
            private UserInfo userInfo;
            private List<UserAssignProj> assignProj;
            public int UserId
            {
                get { return userId; }
                set { userId = value; }
            }
            public string UserName
            {
                get { return userName; }
                set { userName = value; }
            }
            public string UserPwd
            {
                get { return userPwd; }
                set { userPwd = value; }
            }
            public UserInfo UserInfo
            {
                get { return userInfo; }
                set { userInfo = value; }
            }
            public List<UserAssignProj> AssignProj
            {
                get { return assignProj; }
            }
            public User()
            {
                assignProj = new List<UserAssignProj>();
            }
        }
        public class Project
        {
            private int projId;
            private string projName;
            public int ProjId
            {
                get { return projId; }
                set { projId = value; }
            }
            public string ProjName
            {
                get { return projName; }
                set { projName = value; }
            }
        }
        private Dictionary<string, User> users = new Dictionary<string, User>();
        private Dictionary<int, Project> projects = new Dictionary<int, Project>();
        public Dictionary<string, User> Users
        {
            get { return users; }
        }
        public Dictionary<int, Project> Projects
        {
            get { return projects; }
        }
        public UserData()
        {
        }

        public void ReadDb()
        {
            users.Clear();
            projects.Clear();
            FileStream stream = new FileStream(UserDataFileName, FileMode.Open);
            System.IO.Compression.GZipStream zip = new System.IO.Compression.GZipStream(stream, System.IO.Compression.CompressionMode.Decompress);
            byte[] buffer = new byte[4];
            zip.Read(buffer, 0, 4);
            int size = BitConverter.ToInt32(buffer, 0);
            buffer = new byte[size];
            zip.Read(buffer, 0, size);
            zip.Close();
            byte[] data = Convert.FromBase64String(Encoding.ASCII.GetString(buffer));
            XmlReader reader = XmlReader.Create(new MemoryStream(data));
            if (reader.MoveToContent() == XmlNodeType.None) throw new Exception("Wrong Database");
            User user = null;
            Project project = null;
            UserAssignProj assignProj = null;
            do
            {
                switch (reader.Name)
                {
                    case "User":
                        if (reader.NodeType == XmlNodeType.EndElement)
                        {
                            users.Add(user.UserName, user);
                            user = null;
                        }
                        else user = new User();
                        reader.Read();
                        break;
                    case "UserId":
                        user.UserId = reader.ReadElementContentAsInt();
                        break;
                    case "UserName":
                        user.UserName = reader.ReadElementContentAsString();
                        break;
                    case "UserPwd":
                        user.UserPwd = reader.ReadElementContentAsString();
                        break;
                    case "UserInfo":
                        if (reader.NodeType == XmlNodeType.Element) user.UserInfo = new UserInfo();
                        reader.Read();
                        break;
                    case "QQ":
                        user.UserInfo.QQ = reader.ReadElementContentAsString();
                        break;
                    case "MSN":
                        user.UserInfo.MSN = reader.ReadElementContentAsString();
                        break;
                    case "Email":
                        user.UserInfo.Email = reader.ReadElementContentAsString();
                        break;
                    case "Phone":
                        user.UserInfo.Phone = reader.ReadElementContentAsString();
                        break;
                    case "AssignProj":
                        if (reader.NodeType == XmlNodeType.EndElement)
                        {
                            user.AssignProj.Add(assignProj);
                            assignProj = null;
                        }
                        else assignProj = new UserAssignProj();
                        reader.Read();
                        break;
                    case "ProjId":
                        if (project != null) project.ProjId = reader.ReadElementContentAsInt();
                        else assignProj.ProjId = reader.ReadElementContentAsInt();
                        break;
                    case "Job":
                        assignProj.Job = reader.ReadElementContentAsString();
                        break;
                    case "Project":
                        if (reader.NodeType == XmlNodeType.EndElement)
                        {
                            projects.Add(project.ProjId, project);
                            project = null;
                        }
                        else project = new Project();
                        reader.Read();
                        break;
                    case "ProjName":
                        project.ProjName = reader.ReadElementContentAsString();
                        break;
                    default:
                        reader.Read();
                        break;
                }
            } while (reader.NodeType != XmlNodeType.None);
        }

        public void WriteDb()
        {
            XmlWriter wr;
            StringBuilder strbd = new StringBuilder();
            wr = XmlWriter.Create(strbd);
            wr.WriteStartElement("Client");
            foreach (KeyValuePair<string, User> user in users)
            {
                wr.WriteStartElement("User");
                wr.WriteElementString("UserId", user.Value.UserId.ToString());
                wr.WriteElementString("UserName", user.Value.UserName);
                wr.WriteElementString("UserPwd", user.Value.UserPwd);
                if (user.Value.UserInfo != null)
                {
                    wr.WriteStartElement("UserInfo");
                    wr.WriteElementString("QQ", user.Value.UserInfo.QQ);
                    wr.WriteElementString("MSN", user.Value.UserInfo.MSN);
                    wr.WriteElementString("Email", user.Value.UserInfo.Email);
                    wr.WriteElementString("Phone", user.Value.UserInfo.Phone);
                    wr.WriteEndElement();
                }
                foreach (UserAssignProj assignProj in user.Value.AssignProj)
                {
                    wr.WriteStartElement("AssignProj");
                    wr.WriteElementString("ProjId", assignProj.ProjId.ToString());
                    wr.WriteElementString("Job", assignProj.Job);
                    wr.WriteEndElement();
                }
                wr.WriteEndElement();
                wr.Flush();
            }
            foreach (KeyValuePair<int, Project> project in projects)
            {
                wr.WriteStartElement("Project");
                wr.WriteElementString("ProjId", project.Value.ProjId.ToString());
                wr.WriteElementString("ProjName", project.Value.ProjName);
                wr.WriteEndElement();
                wr.Flush();
            }
            wr.WriteEndElement();
            wr.Flush();
            string based = Convert.ToBase64String(Encoding.Unicode.GetBytes(strbd.ToString()));
            byte[] buffer = Encoding.ASCII.GetBytes(based);
            FileStream stream = new FileStream(UserDataFileName, FileMode.Create);
            System.IO.Compression.GZipStream zip = new System.IO.Compression.GZipStream(stream, System.IO.Compression.CompressionMode.Compress);
            zip.Write(BitConverter.GetBytes(buffer.Length), 0, 4);
            zip.Write(buffer, 0, buffer.Length);
            zip.Flush();
            zip.Close();
        }

        public bool Verify(string UserName, string UserPwd)
        {
            User user;
            if (users.TryGetValue(UserName, out user))
            {
                if (user.UserPwd == UserPwd)
                    return true;
                else return false;
            }
            return false;
        }
    }
}
